//
// Created by kunnkali on 2023/5/23.
//

#ifndef Result_H
#define Result_H
#include "Prefix.h"
#include <string>

namespace TNet {
namespace Base {

#define Res_Success Base::Result::ok()
#define Res_Failed(errorMsg) Base::Result::fail(errorMsg, -1)

/*
 *  Represents the 'success' or 'failure' of an operation, and holds an
 * associated error message to describe the error when there's a failure.
 */
class TNET_API Result {
public:
    //==============================================================================
    /** Creates and returns a 'successful' Result. */
    static Result ok() noexcept { return Result(); }
    
    /** Creates a 'failure' Result.
     If you pass a blank error message in here, a default "Unknown Error"
     message will be used instead.
     */
    static Result fail(const std::string &errorMessage) noexcept { return fail(errorMessage, -1); }
    static Result fail(const std::string &errorMessage, int statusCode) noexcept;
    
    //==============================================================================
    /** Returns true if this Result indicates a success. */
    bool isOk() const noexcept;
    
    /** Returns true if this Result indicates a failure.
     You can use getErrorMessage() to retrieve the error message associated
     with the failure.
     */
    bool failed() const noexcept;
    
    /** Returns true if this Result indicates a success.
     This is equivalent to calling isOk().
     */
    operator bool() const noexcept;
    
    /** Returns true if this Result indicates a failure.
     This is equivalent to calling failed().
     */
    bool operator!() const noexcept;
    
    
    /** Returns the status code that was set when this Result was created.
     For a successful Result, this will be an empty string;
     */
    const std::string &getErrorMessage() const noexcept;
    
    /** Returns the error code that was set when this Result was created.
     For a successful Result, this will be default value 0;
     */
    int getStatusCode() const noexcept;
    
    //==============================================================================
    Result(const Result &);
    Result &operator=(const Result &);
    Result(Result &&) noexcept;
    Result &operator=(Result &&) noexcept;
    
    bool operator==(const Result &other) const noexcept;
    bool operator!=(const Result &other) const noexcept;
    
private:
    std::string errorMessage;
    
    int statusCode = 0;
    // The default constructor is not for public use!
    // Instead, use Result::ok() or Result::fail()
    Result() noexcept;
    explicit Result(const std::string &, int) noexcept;
    
    // These casts are private to prevent people trying to use the Result object
    // in numeric contexts
    operator int() const;
    operator void *() const;
};

}// namespace Base
}// namespace TNet

#endif /* Result_hpp */
